/**
 * 本地存储工具函数 - TypeScript版本
 * 提供localStorage、sessionStorage、cookie等存储操作
 * 支持直接复制粘贴使用，无需任何依赖
 * 每个函数都是独立的，可以单独复制使用
 */

// 类型定义
export interface StorageEventDetail {
  type: string;
  key: string | null;
  value: any;
  storageType: string;
  timestamp: number;
}

export interface StorageUsage {
  keyCount: number;
  totalSize: number;
  averageSize: number;
  keys: string[];
}

export interface StorageWithExpiry {
  value: any;
  expiry: number;
}

export type StorageType = 'localStorage' | 'sessionStorage' | 'cookie';

// 常量定义
export const STORAGE_TYPES = {
  LOCAL: 'localStorage',
  SESSION: 'sessionStorage',
  COOKIE: 'cookie'
} as const;

export const STORAGE_EVENTS = {
  SET: 'storage-set',
  GET: 'storage-get',
  REMOVE: 'storage-remove',
  CLEAR: 'storage-clear'
} as const;

/**
 * 设置存储数据
 * @param {string} key - 存储键
 * @param {any} value - 存储值
 * @param {StorageType} type - 存储类型
 * @returns {boolean} 是否成功
 */
export function setStorage(key: string, value: any, type: StorageType = STORAGE_TYPES.LOCAL): boolean {
  if (!key || typeof key !== 'string') {
    console.error('存储键不能为空且必须是字符串');
    return false;
  }

  try {
    const serializedValue = JSON.stringify(value);
    
    switch (type) {
      case STORAGE_TYPES.LOCAL:
        localStorage.setItem(key, serializedValue);
        break;
      case STORAGE_TYPES.SESSION:
        sessionStorage.setItem(key, serializedValue);
        break;
      case STORAGE_TYPES.COOKIE:
        setCookie(key, serializedValue);
        break;
      default:
        console.error('不支持的存储类型:', type);
        return false;
    }
    
    // 触发自定义事件
    dispatchStorageEvent(STORAGE_EVENTS.SET, key, value, type);
    return true;
  } catch (error) {
    console.error('存储数据失败:', error);
    return false;
  }
}

/**
 * 获取存储数据
 * @param {string} key - 存储键
 * @param {any} defaultValue - 默认值
 * @param {StorageType} type - 存储类型
 * @returns {any} 存储值或默认值
 */
export function getStorage(key: string, defaultValue: any = null, type: StorageType = STORAGE_TYPES.LOCAL): any {
  if (!key || typeof key !== 'string') {
    console.error('存储键不能为空且必须是字符串');
    return defaultValue;
  }

  try {
    let serializedValue: string | null = null;
    
    switch (type) {
      case STORAGE_TYPES.LOCAL:
        serializedValue = localStorage.getItem(key);
        break;
      case STORAGE_TYPES.SESSION:
        serializedValue = sessionStorage.getItem(key);
        break;
      case STORAGE_TYPES.COOKIE:
        serializedValue = getCookie(key);
        break;
      default:
        console.error('不支持的存储类型:', type);
        return defaultValue;
    }
    
    if (serializedValue === null) {
      return defaultValue;
    }
    
    const value = JSON.parse(serializedValue);
    
    // 触发自定义事件
    dispatchStorageEvent(STORAGE_EVENTS.GET, key, value, type);
    return value;
  } catch (error) {
    console.error('获取存储数据失败:', error);
    return defaultValue;
  }
}

/**
 * 删除存储数据
 * @param {string} key - 存储键
 * @param {StorageType} type - 存储类型
 * @returns {boolean} 是否成功
 */
export function removeStorage(key: string, type: StorageType = STORAGE_TYPES.LOCAL): boolean {
  if (!key || typeof key !== 'string') {
    console.error('存储键不能为空且必须是字符串');
    return false;
  }

  try {
    switch (type) {
      case STORAGE_TYPES.LOCAL:
        localStorage.removeItem(key);
        break;
      case STORAGE_TYPES.SESSION:
        sessionStorage.removeItem(key);
        break;
      case STORAGE_TYPES.COOKIE:
        removeCookie(key);
        break;
      default:
        console.error('不支持的存储类型:', type);
        return false;
    }
    
    // 触发自定义事件
    dispatchStorageEvent(STORAGE_EVENTS.REMOVE, key, null, type);
    return true;
  } catch (error) {
    console.error('删除存储数据失败:', error);
    return false;
  }
}

/**
 * 清空存储数据
 * @param {StorageType} type - 存储类型
 * @returns {boolean} 是否成功
 */
export function clearStorage(type: StorageType = STORAGE_TYPES.LOCAL): boolean {
  try {
    switch (type) {
      case STORAGE_TYPES.LOCAL:
        localStorage.clear();
        break;
      case STORAGE_TYPES.SESSION:
        sessionStorage.clear();
        break;
      case STORAGE_TYPES.COOKIE:
        clearAllCookies();
        break;
      default:
        console.error('不支持的存储类型:', type);
        return false;
    }
    
    // 触发自定义事件
    dispatchStorageEvent(STORAGE_EVENTS.CLEAR, null, null, type);
    return true;
  } catch (error) {
    console.error('清空存储数据失败:', error);
    return false;
  }
}

/**
 * 获取存储大小
 * @param {StorageType} type - 存储类型
 * @returns {number} 存储大小（字节）
 */
export function getStorageSize(type: StorageType = STORAGE_TYPES.LOCAL): number {
  try {
    let size = 0;
    
    switch (type) {
      case STORAGE_TYPES.LOCAL:
        for (let key in localStorage) {
          if (localStorage.hasOwnProperty(key)) {
            size += localStorage[key].length + key.length;
          }
        }
        break;
      case STORAGE_TYPES.SESSION:
        for (let key in sessionStorage) {
          if (sessionStorage.hasOwnProperty(key)) {
            size += sessionStorage[key].length + key.length;
          }
        }
        break;
      case STORAGE_TYPES.COOKIE:
        size = document.cookie.length;
        break;
      default:
        console.error('不支持的存储类型:', type);
        return 0;
    }
    
    return size;
  } catch (error) {
    console.error('获取存储大小失败:', error);
    return 0;
  }
}

/**
 * 检查存储是否可用
 * @param {StorageType} type - 存储类型
 * @returns {boolean} 是否可用
 */
export function isStorageAvailable(type: StorageType = STORAGE_TYPES.LOCAL): boolean {
  try {
    switch (type) {
      case STORAGE_TYPES.LOCAL:
        const testKey = '__storage_test__';
        localStorage.setItem(testKey, 'test');
        localStorage.removeItem(testKey);
        return true;
      case STORAGE_TYPES.SESSION:
        const sessionTestKey = '__session_test__';
        sessionStorage.setItem(sessionTestKey, 'test');
        sessionStorage.removeItem(sessionTestKey);
        return true;
      case STORAGE_TYPES.COOKIE:
        return navigator.cookieEnabled;
      default:
        return false;
    }
  } catch (error) {
    return false;
  }
}

/**
 * 设置带过期时间的存储
 * @param {string} key - 存储键
 * @param {any} value - 存储值
 * @param {number} expiry - 过期时间（毫秒）
 * @param {StorageType} type - 存储类型
 * @returns {boolean} 是否成功
 */
export function setStorageWithExpiry(key: string, value: any, expiry: number, type: StorageType = STORAGE_TYPES.LOCAL): boolean {
  const expiryTime = Date.now() + expiry;
  const data: StorageWithExpiry = {
    value: value,
    expiry: expiryTime
  };
  
  return setStorage(key, data, type);
}

/**
 * 获取带过期时间的存储
 * @param {string} key - 存储键
 * @param {any} defaultValue - 默认值
 * @param {StorageType} type - 存储类型
 * @returns {any} 存储值或默认值
 */
export function getStorageWithExpiry(key: string, defaultValue: any = null, type: StorageType = STORAGE_TYPES.LOCAL): any {
  const data = getStorage(key, null, type);
  
  if (data === null) {
    return defaultValue;
  }
  
  if (data.expiry && Date.now() > data.expiry) {
    removeStorage(key, type);
    return defaultValue;
  }
  
  return data.value;
}

/**
 * 存储迁移
 * @param {string} fromKey - 源键
 * @param {string} toKey - 目标键
 * @param {StorageType} type - 存储类型
 * @returns {boolean} 是否成功
 */
export function migrateStorage(fromKey: string, toKey: string, type: StorageType = STORAGE_TYPES.LOCAL): boolean {
  const value = getStorage(fromKey, null, type);
  
  if (value === null) {
    return false;
  }
  
  const setResult = setStorage(toKey, value, type);
  if (setResult) {
    removeStorage(fromKey, type);
  }
  
  return setResult;
}

/**
 * 获取所有存储键
 * @param {StorageType} type - 存储类型
 * @returns {Array<string>} 键数组
 */
export function getAllStorageKeys(type: StorageType = STORAGE_TYPES.LOCAL): string[] {
  try {
    const keys: string[] = [];
    
    switch (type) {
      case STORAGE_TYPES.LOCAL:
        for (let i = 0; i < localStorage.length; i++) {
          const key = localStorage.key(i);
          if (key) keys.push(key);
        }
        break;
      case STORAGE_TYPES.SESSION:
        for (let i = 0; i < sessionStorage.length; i++) {
          const key = sessionStorage.key(i);
          if (key) keys.push(key);
        }
        break;
      case STORAGE_TYPES.COOKIE:
        const cookies = document.cookie.split(';');
        cookies.forEach(cookie => {
          const key = cookie.split('=')[0].trim();
          if (key) keys.push(key);
        });
        break;
      default:
        console.error('不支持的存储类型:', type);
        return [];
    }
    
    return keys;
  } catch (error) {
    console.error('获取存储键失败:', error);
    return [];
  }
}

/**
 * 检查存储键是否存在
 * @param {string} key - 存储键
 * @param {StorageType} type - 存储类型
 * @returns {boolean} 是否存在
 */
export function hasStorageKey(key: string, type: StorageType = STORAGE_TYPES.LOCAL): boolean {
  try {
    switch (type) {
      case STORAGE_TYPES.LOCAL:
        return localStorage.getItem(key) !== null;
      case STORAGE_TYPES.SESSION:
        return sessionStorage.getItem(key) !== null;
      case STORAGE_TYPES.COOKIE:
        return getCookie(key) !== null;
      default:
        return false;
    }
  } catch (error) {
    return false;
  }
}

/**
 * 获取存储使用情况
 * @param {StorageType} type - 存储类型
 * @returns {StorageUsage} 使用情况
 */
export function getStorageUsage(type: StorageType = STORAGE_TYPES.LOCAL): StorageUsage {
  const keys = getAllStorageKeys(type);
  const totalSize = getStorageSize(type);
  const keyCount = keys.length;
  
  return {
    keyCount,
    totalSize,
    averageSize: keyCount > 0 ? Math.round(totalSize / keyCount) : 0,
    keys: keys
  };
}

/**
 * 清理过期存储
 * @param {StorageType} type - 存储类型
 * @returns {number} 清理的键数量
 */
export function cleanExpiredStorage(type: StorageType = STORAGE_TYPES.LOCAL): number {
  const keys = getAllStorageKeys(type);
  let cleanedCount = 0;
  
  keys.forEach(key => {
    const data = getStorage(key, null, type);
    if (data && data.expiry && Date.now() > data.expiry) {
      removeStorage(key, type);
      cleanedCount++;
    }
  });
  
  return cleanedCount;
}

/**
 * 监听存储变化
 * @param {Function} callback - 回调函数
 * @param {StorageType} type - 存储类型
 * @returns {Function} 取消监听的函数
 */
export function onStorageChange(callback: (detail: StorageEventDetail) => void, type: StorageType = STORAGE_TYPES.LOCAL): () => void {
  const handleStorageChange = (event: CustomEvent<StorageEventDetail>) => {
    if (event.detail && event.detail.storageType === type) {
      callback(event.detail);
    }
  };
  
  window.addEventListener('storage', handleStorageChange as EventListener);
  
  // 返回取消监听的函数
  return () => {
    window.removeEventListener('storage', handleStorageChange as EventListener);
  };
}

// Cookie 相关辅助函数
function setCookie(name: string, value: string, days: number = 7): void {
  const expires = new Date();
  expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
  document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;
}

function getCookie(name: string): string | null {
  const nameEQ = name + "=";
  const ca = document.cookie.split(';');
  for (let i = 0; i < ca.length; i++) {
    let c = ca[i];
    while (c.charAt(0) === ' ') c = c.substring(1, c.length);
    if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
  }
  return null;
}

function removeCookie(name: string): void {
  document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`;
}

function clearAllCookies(): void {
  const cookies = document.cookie.split(';');
  cookies.forEach(cookie => {
    const eqPos = cookie.indexOf('=');
    const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
    document.cookie = `${name.trim()}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`;
  });
}

// 事件分发函数
function dispatchStorageEvent(eventType: string, key: string | null, value: any, type: StorageType): void {
  const event = new CustomEvent('storage', {
    detail: {
      type: eventType,
      key: key,
      value: value,
      storageType: type,
      timestamp: Date.now()
    }
  });
  
  window.dispatchEvent(event);
}
